package com.hl.widget;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;

import com.google.gson.reflect.TypeToken;
import com.hl.R;
import com.hl.app.XiaoMiApplication;
import com.hl.bean.RecommendShop;
import com.hl.ui.ShopDetailActitity;
import com.hl.util.LogUtils;
import com.hl.util.KL.XmClients.IRequestCallback;
import com.hl.util.KL.XmClients.RequestMethod;
import com.hl.util.KL.XmClients.SendResult;
import com.hl.util.KL.XmClients.XmClient;
import com.hl.util.loaderConfig.ImageLoaderConfig;
import com.hl.util.loaderConfig.WaterFallImgLoadListener;
import com.hl.util.loaderConfig.XMImageSize;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;

/**
 * @title 瀑布流视图
 * @createDate 2014-01-16
 * @description 自定义的ScrollView，在其中动态地对图片进行添加。
 *              实现原理，瀑布流的布局方式虽然看起来好像排列的很随意，其实它是有很科学的排列规则的
 *              。整个界面会根据屏幕的宽度划分成等宽的若干列，由于手机的屏幕不是很大
 *              ，这里我们就分成三列。每当需要添加一张图片时，会将这张图片的宽度压缩成和列一样宽，再按照同样的压缩比例对图片的高度进行压缩，
 *              然后在这三列中找出当前高度最小的一列
 *              ，将图片添加到这一列中。之后每当需要添加一张新图片时，都去重复上面的操作，就会形成瀑布流格局的照片墙
 * @author 田进勇
 */
public class WaterfallScrollView extends ScrollView implements OnTouchListener,
		IRequestCallback {
	private static String TAG = WaterfallScrollView.class.getSimpleName();
	// /** 图片的url */
	// private String[] imageUrls = new String[] {
	// "http://img.my.csdn.net/uploads/201309/01/1378037235_3453.jpg",
	// "http://img.my.csdn.net/uploads/201309/01/1378037235_7476.jpg",
	// "http://img.my.csdn.net/uploads/201309/01/1378037235_9280.jpg",
	// "http://img.my.csdn.net/uploads/201309/01/1378037234_3539.jpg",
	// "http://img.my.csdn.net/uploads/201309/01/1378037234_6318.jpg",
	// "http://img.my.csdn.net/uploads/201309/01/1378037194_2965.jpg",
	// "http://img.my.csdn.net/uploads/201309/01/1378037193_1687.jpg",
	// "http://img.my.csdn.net/uploads/201309/01/1378037193_1286.jpg",
	// "http://img.my.csdn.net/uploads/201309/01/1378037192_8379.jpg",
	// "http://img.my.csdn.net/uploads/201309/01/1378037178_9374.jpg",
	// "http://img.my.csdn.net/uploads/201309/01/1378037177_1254.jpg",
	// "http://img.my.csdn.net/uploads/201309/01/1378037177_6203.jpg",
	// "http://img.my.csdn.net/uploads/201309/01/1378037152_6352.jpg",
	// "http://img.my.csdn.net/uploads/201309/01/1378037151_9565.jpg",
	// "http://img.my.csdn.net/uploads/201309/01/1378037151_7904.jpg",
	// "http://img.my.csdn.net/uploads/201309/01/1378037148_7104.jpg",
	// "http://img.my.csdn.net/uploads/201309/01/1378037129_8825.jpg",
	// "http://img.my.csdn.net/uploads/201309/01/1378037128_5291.jpg",
	// "http://img.my.csdn.net/uploads/201309/01/1378037128_3531.jpg",
	// "http://img.my.csdn.net/uploads/201309/01/1378037127_1085.jpg",
	// "http://img.my.csdn.net/uploads/201309/01/1378037095_7515.jpg",
	// "http://img.my.csdn.net/uploads/201309/01/1378037094_8001.jpg",
	// "http://img.my.csdn.net/uploads/201309/01/1378037093_7168.jpg",
	// "http://img.my.csdn.net/uploads/201309/01/1378037091_4950.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949643_6410.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949642_6939.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949630_4505.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949630_4593.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949629_7309.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949629_8247.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949615_1986.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949614_8482.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949614_3743.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949614_4199.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949599_3416.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949599_5269.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949598_7858.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949598_9982.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949578_2770.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949578_8744.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949577_5210.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949577_1998.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949482_8813.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949481_6577.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949480_4490.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949455_6792.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949455_6345.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949442_4553.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949441_8987.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949441_5454.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949454_6367.jpg",
	// "http://img.my.csdn.net/uploads/201308/31/1377949442_4562.jpg" };
	/**
	 * 单例模式
	 */
	private static WaterfallScrollView wfSVinfo;

	public static WaterfallScrollView getInstance() {
		return wfSVinfo;
	}

	/**
	 * 商圈 默认为空白字符串
	 */
	public static String circle = "";

	/**
	 * 每页要加载的图片数量
	 */
	public static int PAGE_SIZE = 12;

	/**
	 * 记录当前已加载到第几页
	 */
	public static int page;

	/**
	 * 门店类型 0-KTV 1-餐饮 -1-全部,记录传入类型参数 默认为-1,
	 */
	public static int storeType = -1;

	/**
	 * 每一列的宽度
	 */
	private int columnWidth;

	/**
	 * 当前第一列的高度
	 */
	private int firstColumnHeight;

	/**
	 * 当前第二列的高度
	 */
	private int secondColumnHeight;

	/**
	 * 是否已加载过一次layout，这里onLayout中的初始化只需加载一次
	 */
	private boolean loadOnce;

	/**
	 * 第一列的布局
	 */
	private LinearLayout firstColumn;

	/**
	 * 第二列的布局
	 */
	private LinearLayout secondColumn;

	/**
	 * 记录所有正在下载或等待下载的任务。
	 * 
	 */
	private static Set<LoadImageTask> taskCollection;

	/**
	 * MyScrollView下的直接子布局。
	 */
	private static View scrollLayout;

	/**
	 * 记录上垂直方向的滚动距离。
	 */
	private static int lastScrollY = -1;

	/**
	 * 记录所有界面上的图片，用以可以随时控制对图片的释放。
	 */
	private List<ImageView> imageViewList = new ArrayList<ImageView>();

	/**
	 * 图片加载对象
	 */
	private ImageLoader imgLoader = ImageLoader.getInstance();

	/**
	 * 在Handler中进行图片可见性检查的判断，以及加载更多图片的操作。
	 */
	private static Handler handler = new Handler() {

		public void handleMessage(android.os.Message msg) {

			WaterfallScrollView myScrollView = (WaterfallScrollView) msg.obj;
			int scrollY = myScrollView.getScrollY();
			/** ScrollView当中子布局的高度 */
			int childLayoutHeit = scrollLayout.getHeight();
			DisplayMetrics metric = myScrollView.getContext().getResources()
					.getDisplayMetrics();

			int screenHeight = metric.heightPixels;
			// 如果当前的滚动位置和上次相同，表示已停止滚动
			if (scrollY == lastScrollY) {
				// 当滚动的最底部，并且当前没有正在下载的任务时，开始加载下一页的图片
				// if (screenHeight + scrollY >= childLayoutHeit
				// && taskCollection.isEmpty()) {
				// myScrollView.loadShopData(storeType, "", page, PAGE_SIZE);
				// }
				if (screenHeight + scrollY >= childLayoutHeit) {
					myScrollView.loadShopData(storeType, "", page, PAGE_SIZE);
				}

				myScrollView.checkVisibility();
			}
			//
			else {
				lastScrollY = scrollY;
				Message message = new Message();
				message.obj = myScrollView;
				// 5毫秒后再次对滚动位置进行判断
				handler.sendMessageDelayed(message, 5);
			}
		};

	};

	/** 访问服务器对象 */
	private XmClient<ArrayList<RecommendShop>> client;
	/** 数据源 */
	public static ArrayList<RecommendShop> shopData = new ArrayList<RecommendShop>();

	/**
	 * MyScrollView的构造函数。
	 * 
	 * @param context
	 * @param attrs
	 */
	public WaterfallScrollView(Context context, AttributeSet attrs) {
		super(context, attrs);
		taskCollection = new HashSet<LoadImageTask>();
		setOnTouchListener(this);

		wfSVinfo = this;
	}

	/**
	 * 进行一些关键性的初始化操作，获取MyScrollView的高度，以及得到第一列的宽度值。并在这里开始加载第一页的图片，从来服务器下载数据
	 */
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		super.onLayout(changed, l, t, r, b);
		if (changed && !loadOnce) {
			scrollLayout = getChildAt(0);
			firstColumn = (LinearLayout) findViewById(R.id.first_column);
			secondColumn = (LinearLayout) findViewById(R.id.second_column);
			columnWidth = firstColumn.getWidth();
			loadOnce = true;
			// 在集合中先加入一默认张图
			RecommendShop rs = new RecommendShop();
			rs.setImgUrl("");
			shopData.add(rs);

			loadShopData(-1, "", page, PAGE_SIZE);
			// loadMoreImages();
		}
	}

	/**
	 * 从服务器获取分页推荐店面
	 * 
	 * @param storeType
	 *            门店类型 0-KTV 1-餐饮 -1-全部
	 * @param circle
	 *            商圈
	 * @param pageIndex
	 *            页索引
	 * @param pageSize
	 *            页大小
	 */
	public void loadShopData(int storeType, String circle, int pageIndex,
			int pageSize) {

		this.storeType = storeType;
		this.circle = circle;
		// 实例化访问对象
		client = new XmClient<ArrayList<RecommendShop>>(getContext());
		try {
			client.AddParam("StoreType", storeType);
			client.AddParam("Circle", circle);
			double a = XiaoMiApplication.getInstance().latitude;
			client.AddParam("Latitude", a);
			double b = XiaoMiApplication.getInstance().longitude;
			client.AddParam("Longitude", b);

			client.AddParam("pageIndex", pageIndex);
			client.AddParam("pageSize", pageSize);
			client.AddParam("CityName", "成都市");
			client.setMethod(RequestMethod.Get);
			client.setRequestPath("/api/Stores/Recommend");

			Type type = new TypeToken<SendResult<ArrayList<RecommendShop>>>() {
			}.getType();
			client.Send(type, this);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 监听用户的触屏事件，如果用户手指离开屏幕则开始进行滚动检测。
	 */
	@Override
	public boolean onTouch(View v, MotionEvent event) {
		if (event.getAction() == MotionEvent.ACTION_UP) {
			Message message = new Message();
			message.obj = this;
			handler.sendMessageDelayed(message, 5);
		}
		return false;
	}

	/**
	 * 开始加载下一页的图片，每张图片都会开启一个异步线程去下载。
	 */
	public void loadMoreImages() {
		int startIndex = page * PAGE_SIZE;
		int endIndex = page * PAGE_SIZE + PAGE_SIZE;

		if (startIndex < shopData.size()) {
			Toast.makeText(getContext(), "正在加载...", Toast.LENGTH_SHORT).show();
			if (endIndex > shopData.size()) {
				endIndex = shopData.size();
			}

			for (int i = startIndex; i < endIndex; i++) {
				LoadImageTask task = new LoadImageTask();
				taskCollection.add(task);

				// 拼接图片地址
				String root = getContext().getResources().getString(
						R.string.host);
				task.execute(root + shopData.get(i).getImgUrl(), i);
			}
			page++;
		} else {
			Toast.makeText(getContext(), "到底啦", Toast.LENGTH_SHORT).show();
		}

	}

	/**
	 * 遍历imageViewList中的每张图片，对图片的可见性进行检查，如果图片已经离开屏幕可见范围，则将图片替换成一张空图。
	 */
	public void checkVisibility() {
		// for (int i = 0; i < imageViewList.size(); i++) {
		// ImageView imageView = imageViewList.get(i);
		// int borderTop = (Integer) imageView.getTag(R.string.border_top);
		// int borderBottom = (Integer) imageView
		// .getTag(R.string.border_bottom);
		// if (borderBottom > getScrollY()
		// && borderTop < getScrollY() + scrollViewHeight) {
		// String imageUrl = (String) imageView.getTag(R.string.image_url);
		// Bitmap bitmap = imageLoader.getBitmapFromMemoryCache(imageUrl);
		// if (bitmap != null) {
		// imageView.setImageBitmap(bitmap);
		// } else {
		// LoadImageTask task = new LoadImageTask(imageView);
		// task.execute(imageUrl);
		// }
		// } else {
		// imageView.setImageResource(R.drawable.empty_photo);
		// }
		// }
	}

	/**
	 * 异步下载图片的任务。
	 * 
	 * @author guolin
	 */
	class LoadImageTask {
		/**
		 * 图片的URL地址
		 */
		private String mImageUrl;

		/**
		 * 可重复使用的ImageView
		 */
		private ImageView mImageView;
		private ViewGroup rootView;
		/** 标识图片是第几张 */
		private int imgIndex;

		public LoadImageTask() {
		}

		/**
		 * 将可重复使用的ImageView传入
		 * 
		 * @param imageView
		 */
		public LoadImageTask(ImageView imageView) {
			mImageView = imageView;
		}

		/**
		 * 获取图片
		 * 
		 * @param url
		 *            图片的地址
		 */
		public void execute(String url, final int imgIndex) {
			this.imgIndex = imgIndex;

			// 第一张图片
			if (imgIndex == 0) {
				Drawable d = getResources().getDrawable(
						R.drawable.discover_nt_04);
				Bitmap bitmap = ((BitmapDrawable) d).getBitmap();

				double ratio = bitmap.getWidth() / (columnWidth * 1.0);
				int scaledHeight = (int) (bitmap.getHeight() / ratio);
				addImage(bitmap, columnWidth, scaledHeight, imgIndex);
			}
			// 不是第一张图片
			else {
				url = XMImageSize.imgFor680x408(url);
				imgLoader.loadImage(url,
						ImageLoaderConfig.initDisplayOptions(true),
						new WaterFallImgLoadListener() {

							@Override
							public void onLoadingCancelled(String arg0,
									View arg1) {
								LogUtils.i("wf--onLoadingCancelled", arg0);
								taskCollection.remove(this);
							}

							@Override
							public void onLoadingFailed(String arg0, View arg1,
									FailReason arg2) {
								LogUtils.i("wf--onLoadingFailed", arg0);
								taskCollection.remove(this);
							}

							@Override
							public void onLoadingComplete(String arg0,
									View arg1, Bitmap bitmap) {
								LogUtils.i("wf--onLoadingComplete", arg0);
								// 第一张图片是默认的图片
								if (bitmap == null) {
									taskCollection.remove(this);
									return;
								}

								double ratio = bitmap.getWidth()
										/ (columnWidth * 1.0);
								int scaledHeight = (int) (bitmap.getHeight() / ratio);
								addImage(bitmap, columnWidth, scaledHeight,
										imgIndex);
								taskCollection.remove(this);
							}
						});
			}

		}

		/**
		 * 向ImageView中添加一张图片
		 * 
		 * @param bitmap
		 *            待添加的图片
		 * @param imageWidth
		 *            图片的宽度
		 * @param imageHeight
		 *            图片的高度
		 */
		private void addImage(Bitmap bitmap, int imageWidth, int imageHeight,
				final int position) {
			LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
					imageWidth, imageHeight);
			if (position > shopData.size())
				return;
			// 取出数据
			final RecommendShop rs = shopData.get(position);

			if (rootView != null) {
				mImageView = (ImageView) rootView.getChildAt(0);
				mImageView.setImageBitmap(bitmap);
			}

			// 存在
			else {
				ImageView imageView = new ImageView(getContext());
				imageView.setLayoutParams(params);
				imageView.setImageBitmap(bitmap);
				imageView.setScaleType(ScaleType.FIT_XY);
				imageView.setPadding(5, 8, 5, 5);
				imageView.setTag(R.string.image_url, mImageUrl);

				rootView = (ViewGroup) LayoutInflater.from(getContext())
						.inflate(R.layout.inscroll_gird_content, null);

				if (position != 0) {

					TextView shopName = (TextView) rootView
							.findViewById(R.id.recommend_shop_name_tv);
					TextView pcTv = (TextView) rootView
							.findViewById(R.id.tv_percapita_consumption);
					TextView dsTv = (TextView) rootView
							.findViewById(R.id.tv_distance);

					shopName.setText(rs.getStoreName());
					pcTv.setText("￥" + rs.getPercapitaConsumption() + "");

					// double distance = rs.getDistance() / 1000.0;
					// // 距离大于1000m应该 显示为 1KM
					// if (distance >= 1000) {
					// distance = (double) Math.round(distance * 100) / 100;
					// } else {
					// distance = (double) Math.round(distance * 10) / 10;
					// }

					if (rs != null && rs.getDistance() != null) {

						dsTv.setText(rs.getDistance().substring(0,
								rs.getDistance().indexOf("."))
								+ "m");
					}
				}

				rootView.addView(imageView, 0);

				findColumnToAdd(imageView, imageHeight).addView(rootView);

				imageViewList.add(imageView);
			}
			// // 第一张图片的时候需要隐藏下面的2个布局
			if (position == 0) {
				rootView.getChildAt(1).setVisibility(View.GONE);
				rootView.getChildAt(2).setVisibility(View.GONE);
			}

			if (position != 0)
				rootView.setOnClickListener(new OnClickListener() {

					@Override
					public void onClick(View v) {

						if (position >= shopData.size())
							return;
						LogUtils.i(TAG, "WaterfallItemOnClicked:" + storeType
								+ " rs:" + rs.getStoreType());
						Intent intent = new Intent(WaterfallScrollView.this
								.getContext(), ShopDetailActitity.class);
						intent.putExtra("ShopId", rs.getId());
						if (storeType == 0) {
							intent.putExtra("StyleAction", "KTV");
						} else {
							intent.putExtra("StyleAction", "美食");
						}
						WaterfallScrollView.this.getContext().startActivity(
								intent);
					}
				});
			// }
		}

		/**
		 * 找到此时应该添加图片的一列。原则就是对三列的高度进行判断，当前高度最小的一列就是应该添加的一列。
		 * 
		 * @param imageView
		 * @param imageHeight
		 * @return 应该添加图片的一列
		 */
		private LinearLayout findColumnToAdd(ImageView imageView,
				int imageHeight) {
			if (firstColumnHeight <= secondColumnHeight) {
				imageView.setTag(R.string.border_top, firstColumnHeight);
				firstColumnHeight += imageHeight;
				imageView.setTag(R.string.border_bottom, firstColumnHeight);

				return firstColumn;
			} else {
				imageView.setTag(R.string.border_top, secondColumnHeight);
				secondColumnHeight += imageHeight;
				imageView.setTag(R.string.border_bottom, secondColumnHeight);

				return secondColumn;
			}
		}

	}

	@Override
	public void Callback(SendResult<?> result) {
		SendResult<ArrayList<RecommendShop>> sendResult = (SendResult<ArrayList<RecommendShop>>) result;
		if (result.getData() == null) {
			Toast.makeText(getContext(), "你的网络不稳定，连接超时！", Toast.LENGTH_SHORT)
					.show();
			return;
		}
		if (sendResult.getData().size() <= 0) {
			Toast.makeText(getContext(), "没有推荐信息，看看其他的吧！", Toast.LENGTH_LONG)
					.show();
			return;
		}
		// 数据拷贝
		for (RecommendShop rs : sendResult.getData()) {
			shopData.add(rs);
		}
		loadMoreImages();
	}

	public static int getPageSize() {
		return PAGE_SIZE;
	}

	public static int getPage() {
		return page;
	}

	/**
	 * 清除数据，以及被添加的子试图
	 */
	public void clear() {
		shopData.clear();
		// 在集合中先加入一默认张图
		RecommendShop rs = new RecommendShop();
		rs.setImgUrl("");
		shopData.add(rs);
		page = 0;

		if (firstColumn == null)
			return;
		firstColumn.removeAllViews();

		if (secondColumn == null)
			return;
		secondColumn.removeAllViews();
	}
}